package wanxiang

import (
	"fmt"
	"gitee.com/gam6it/SecToolkit/utils/http2"
)

type Host struct {
	AgentId      string   `json:"agentId"`
	DisplayIp    string   `json:"displayIp"`
	ConnectionIp string   `json:"connectionIp"`
	ExternalIp   string   `json:"externalIp"`
	InternalIp   string   `json:"internalIp"`
	BizGroupId   int      `json:"bizGroupId"`
	BizGroup     string   `json:"bizGroup"`
	Remark       string   `json:"remark"`
	HostTagList  []string `json:"hostTagList"`
	HostName     string   `json:"hostname"` // 主机名
	ProxyIp      string   `json:"proxyIp"`  // 代理ip，仅linux可用
	Platform     string   `json:"platform"` // 操作系统信息
	CPU          struct {
		Core            int     `json:"core"`
		Producer        string  `json:"producer"`
		Brand           string  `json:"brand"`
		Description     string  `json:"description"`
		LoadAvgFifteen  float64 `json:"loadAvgFifteen"`
		CPUNum          int     `json:"cpuNum"`
		CPUArch         string  `json:"cpuArch"`
		ClockSpeed      float64 `json:"clockSpeed"`
		PhysicalCoreNum int     `json:"physicalCoreNum"`
		LogicalCoreNum  int     `json:"logicalCoreNum"`
	} `json:"cpu"`
	MemorySize      int    `json:"memorySize"`   // 内存大小，单位MB
	OnlineStatus    int    `json:"onlineStatus"` // 通信状态 1 – 在线 0 - 离线
	AgentStatus     int    `json:"agentStatus"`  // Agent状态，0-在线 1-离线 2-停用 3-删除中
	LastOnlineTime  string `json:"lastOnlineTime"`
	LastOfflineTime string `json:"lastOfflineTime"`
	InstallTime     string `json:"installTime"`
	AgentVersion    string `json:"agentVersion"`
	DiskSize        int    `json:"diskSize"` // 硬盘大小，单位MB
	OfflineDays     int    `json:"offlineDays"`
	ChargeName      string `json:"chargeName"`
	HostLocation    string `json:"hostLocation"`
	Memories        []struct {
		Type         string `json:"type"`
		Producer     string `json:"producer"`
		Size         int    `json:"size"`
		Speed        int    `json:"speed"`
		Description  string `json:"description"`
		ProducerSize int    `json:"producerSize"`
		Bank         string `json:"bank"`
	} `json:"memories"`
	Manufacturer string `json:"manufacturer"` // 生产商
	ProductName  string `json:"productName"`
	SerialNumber string `json:"serialNumber"` // 设备序列号
	NetworkCards []struct {
		Name      string   `json:"name"`
		Mac       string   `json:"mac"`
		Ipv4      string   `json:"ipv4"`
		Ipv6      string   `json:"ipv6"`
		Gateway   string   `json:"gateway"`
		DnsServer []string `json:"dnsServer"`
		Netmask   string   `json:"netmask"`
		Broadcast string   `json:"broadcast"`
		Status    string   `json:"status"`
		Speed     int      `json:"speed"`
	} `json:"networkCards"`
	Uuid                string  `json:"uuid"`
	KernelVersion       string  `json:"kernelVersion"`
	BashVersion         string  `json:"bashVersion"`
	BashPluginInstalled bool    `json:"bashPluginInstalled"` // bash是否安装 true-安装 false-未安装 仅linux可用
	MemoryUsage         float64 `json:"memoryUsage"`
	DiskUsage           float64 `json:"diskUsage"`
	DiskCount           int     `json:"diskCount"`
	SystemLoad          int     `json:"systemLoad"`
}

const (
	HostOSTypeWin      = "win"
	HostOSTypeLinux    = "linux"
	AgentStatusOnline  = 0 // 主机状态，0-在线
	AgentStatusOffline = 1 // 主机状态，1-离线
	AgentStatusDisable = 2 // 主机状态，2-停用
)

type HostFilterOption struct {
	OS             string     `json:"-"` // win、linux
	Page           int        `json:"page"`
	Size           int        `json:"size"`
	AgentId        string     `json:"agentId,omitempty"`        // 唯一标识Agent的ID
	HostName       string     `json:"hostname,omitempty"`       // 主机名（模糊查询）
	IP             string     `json:"ip,omitempty"`             // 主机IP（模糊查询）
	Platform       string     `json:"platform,omitempty"`       // 操作系统
	LastOnlineTime *DateRange `json:"lastOnlineTime,omitempty"` // 最后一次在线时间，yyyy-MM-dd HH:mm:ss - yyyy-MM-dd HH:mm:ss
	AgentStatus    string     `json:"agentStatus,omitempty"`    // 主机状态，0-在线 1-离线 2-停用
	SerialNumber   string     `json:"serialNumber,omitempty"`   // 序列号
}

// GetHostByPage 获取主机列表
func (c *Client) GetHostByPage(opt HostFilterOption) (int64, *[]Host, error) {
	if opt.OS != HostOSTypeWin && opt.OS != HostOSTypeLinux {
		return 0, &[]Host{}, fmt.Errorf("参数OS错误，可选值win、linux")
	}
	if opt.Size <= 0 {
		return 0, &[]Host{}, fmt.Errorf("参数size错误不能为0")
	}
	type resp struct {
		Total int64  `json:"total"`
		Rows  []Host `json:"rows"`
	}
	var result resp
	var api = "external/api/assets/host/" + opt.OS
	err := c.Request(http2.MethodGet, api, &result, opt)
	return result.Total, &result.Rows, err
}

// GetHosts 获取所有主机,不区分操作系统，从page 0开始
func (c *Client) GetHosts(opt HostFilterOption) (int64, *[]Host, error) {
	if opt.Page != 0 {
		return 0, &[]Host{}, fmt.Errorf("参数page错误，只能为0")
	}
	var osTypes []string
	if opt.OS == "" {
		osTypes = []string{HostOSTypeWin, HostOSTypeLinux}
	} else {
		osTypes = []string{opt.OS}
	}
	opt.Size = 1000
	var hosts []Host
	var total int64
	for _, osType := range osTypes {
		opt.OS = osType
		for true {
			t, hs, err := c.GetHostByPage(opt)
			if err != nil {
				return 0, nil, err
			}
			if len(*hs) == 0 { // 如果查询不到则退出循环
				total += t
				break
			} else if len(*hs) < opt.Size { // 如果查询到的数量小于size则退出循环
				total += t
				hosts = append(hosts, *hs...)
				break
			}
			hosts = append(hosts, *hs...)
			opt.Page += 1
		}
	}
	return total, &hosts, nil
}

func (c *Client) GetHostByIP(ip string) (Host, error) {
	opt := HostFilterOption{
		Page: 0,
		Size: 1,
		IP:   ip,
	}
	for _, osType := range []string{HostOSTypeWin, HostOSTypeLinux} {
		opt.OS = osType
		cnt, hosts, err := c.GetHostByPage(opt)
		if err != nil {
			return Host{}, err
		}
		if cnt == 0 || len(*hosts) < 1 { // 没有找到
			continue
		}
		return (*hosts)[0], nil
	}
	return Host{}, fmt.Errorf("未找到IP为%s的主机", ip)
}

// HostFresh 刷新主机信息，返回刷新任务id
func (c *Client) HostFresh(osType string) (string, error) {
	type resp struct {
		ID           string `json:"id,omitempty"`
		ErrorCode    int    `json:"errorCode,omitempty"`
		ErrorMessage string `json:"errorMessage,omitempty"`
	}
	var result resp
	api := fmt.Sprintf("/external/api/assets/host/%s/refresh", osType)
	err := c.Request(http2.MethodPost, api, &result, nil)
	fmt.Println("result:", result)
	if err != nil || result.ErrorCode != 0 {
		return "", fmt.Errorf("刷新主机失败，错误码：%d，错误信息：%s，错误内容：%v", result.ErrorCode, result.ErrorMessage, err)
	}
	return result.ID, nil
}
